package com.grape.ciq.api.redbook;

import cn.hutool.crypto.digest.MD5;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.grape.ciq.api.redbook.base.XHSClient;
import com.grape.ciq.api.redbook.base.XHSRequest;
import com.grape.ciq.api.redbook.base.XHSResponse;
import com.grape.ciq.api.redbook.internal.parse.WebUtils;
import com.grape.ciq.api.redbook.internal.parse.json.ObjectJsonParse;
import com.grape.ciq.plat.Shop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultXHSClient extends XHSClient {

    private static final Logger LOG = LoggerFactory.getLogger(DefaultXHSClient.class);

    /**
     * 生成请求的url
     *
     * @param request
     * @return
     * @throws ApiException
     */
    private <T extends XHSResponse> Map<String, String> createUrl(XHSRequest<T> request, Shop shopApp) throws ApiException {
        //将url的所有请求参数以及除sign外的系统参数按照字母序进行排序（如果参数包含中文，中文保持原文即可，无需对其单独转码），并使用&连接， 请求body不参与排序
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

        //获取配置表中key等参数
        String appKey = shopApp.getPlatAppId();
        String appSecret = shopApp.getPlatAppSecret();
        String url = shopApp.getPlatApiUrl();
        String methodUrl = request.getMethodUrl();

        //md5加密，需添加app_key,timestamp
        String md5Params = "";
        //调用地址，无需添加app_key,timestamp
        String urlParams = "";
        //md5密文
        String sign = "";

        //1.从实体中获取API参数并添加两个需要参加排序的参数 计算sign需要
        Map<String, Object> signMap = new HashMap<>();
        //2.从实体中获取API参数并添加两个需要参加排序的参数  URL拼接需要
        Map<String, Object> urlMap = new HashMap<>();

        if (request.getParams() != null && request.getMethod().equals("GET")) {
            signMap = request.getParams();
            urlMap = request.getParams();
        }

        //添加key + time + key按照字母序进行排序		
        signMap.put("app-key", appKey);
        signMap.put("timestamp", timestamp);
        List<String> mapList = new ArrayList<>(signMap.keySet());
        Collections.sort(mapList);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < mapList.size(); i++) {
            if (StringUtils.isNotBlank(signMap.get(mapList.get(i)) + "")) {
                sb.append(mapList.get(i)).append("=").append(signMap.get(mapList.get(i))).append("&");
            }
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);//去除最后一个&  end_time=1526276566&logistics=&page_no=1&page_size=11&start_time=1526275366&status=waiting
        }
        md5Params = sb.toString();

        //key按照字母序进行排序
        List<String> mapList2 = new ArrayList<>(urlMap.keySet());
        Collections.sort(mapList2);
        StringBuilder sb2 = new StringBuilder();
        for (int i = 0; i < mapList2.size(); i++) {
            if (StringUtils.isNotBlank(urlMap.get(mapList2.get(i)) + "")) {
                sb2.append(mapList2.get(i)).append("=").append(urlMap.get(mapList2.get(i))).append("&");
            }
        }
        if (sb2.length() > 0) {
            sb2.deleteCharAt(sb2.length() - 1);//去除最后一个&  end_time=1526276566&logistics=&page_no=1&page_size=11&start_time=1526275366&status=waiting
        }
        urlParams = sb2.toString();

        String methodUrlMd5 = "";
        String methodUrl2 = "";
        if (!methodUrl.contains("?")) {
            methodUrlMd5 = methodUrl + request.getUrlParams() + "?";
            methodUrl2 = methodUrl + request.getUrlParams();
            if (request.getMethod().equals("PUT") || request.getMethod().equals("POST")) {
                methodUrl2 = methodUrl + request.getUrlParams();
                methodUrlMd5 = methodUrl + request.getUrlParams() + "?";
                urlParams = "";
            }
        } else {
            methodUrl2 = methodUrl;
            methodUrlMd5 = methodUrl;
        }

        //拼接加密所需要参数
        MD5 md5 = new MD5();
        sign = md5.digestHex(methodUrlMd5 + md5Params + appSecret);

        Map<String, String> mapXHS = new HashMap<>();
        mapXHS.put("url", url + methodUrl2 + urlParams);
        mapXHS.put("sign", sign);
        return mapXHS;
    }

    public <T extends XHSResponse> T execute(XHSRequest<T> request, Shop shopApp) throws ApiException {

        request.check();

        String resp = "";

        Map<String, String> map = createUrl(request, shopApp);
        String url = map.get("url");
        String sign = map.get("sign");
        LOG.info("url---->" + url);

        try {
            // 将请求对象转为json格式
            String req = ObjectJsonParse.toJson(request.getParams(), true);
            if (request.getMethod().equals("POST") || request.getMethod().equals("PUT")) {
                LOG.info("post请求对象--->" + req);
            }
//			req = URLEncoder.encode(req, "utf-8");
//			req = "jsondata=" + req;
//			logger.info("编码后 postdate---->" + req);

            // 发起请求
            if (url.toUpperCase().contains("HTTPS://")) {
                resp = WebUtils.httpsRequest(url, req, request.getMethod(), sign, shopApp.getPlatAppId());
//				resp = MyHttps.get(url, req, request.getMethod(),sign,shopApp.getAppKey());
            } else {
                resp = WebUtils.httpRequest(url, req, request.getMethod(), sign, shopApp.getPlatAppId());
            }
            LOG.info(resp);

        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
        }

        if (resp == null || resp.equals("")) {
            return null;
        }
        //转为对象
        T response = null;

        try {
            response = (T) ObjectJsonParse.fromJson(resp, request.getResponseClass());

            if (response != null) {
                response.setResponseBody(resp);
            }
            return response;
        } catch (JsonMappingException e) {
            LOG.error(e.getMessage(), e);
        } catch (JsonParseException e) {
            LOG.error(e.getMessage(), e);
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        }
        return response;
    }

}
